home *** CD-ROM | disk | FTP | other *** search
/ Delphi 5 for Professionals / DELPHI5.iso / AddOns / Components / Orpheus v3.02 / SETUP.EXE / %MAINDIR% / Ovceditn.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-02-25  |  19.5 KB  |  739 lines

  1. {*********************************************************}
  2. {*                  OVCEDITN.PAS 3.00                    *}
  3. {*     Copyright (c) 1995-99 TurboPower Software Co      *}
  4. {*                 All rights reserved.                  *}
  5. {*********************************************************}
  6.  
  7. {$I OVC.INC}
  8.  
  9. {$B-} {Complete Boolean Evaluation}
  10. {$I+} {Input/Output-Checking}
  11. {$P+} {Open Parameters}
  12. {$T-} {Typed @ Operator}
  13. {$W-} {Windows Stack Frame}
  14. {$X+} {Extended Syntax}
  15.  
  16. {$IFNDEF Win32}
  17. {$G+} {286 Instructions}
  18. {$N+} {Numeric Coprocessor}
  19.  
  20. {$C MOVEABLE,DEMANDLOAD,DISCARDABLE}
  21. {$ENDIF}
  22.  
  23. unit OvcEditN;
  24.   {Editor paragraph node handling}
  25.  
  26. interface
  27.  
  28. uses
  29.   OvcConst, OvcData;
  30.  
  31. {.Z+}
  32. type
  33.   UndoType = (
  34.     utSavePos,   {save a position}
  35.     utInsert,    {an insertion within a paragraph}
  36.     utInsPara,   {an insertion of an entire paragraph before another}
  37.     utPlacePara, {an insertion of an entire paragraph after another}
  38.     utDelete,    {a deletion within a paragraph}
  39.     utDelPara,   {a deletion of an entire paragraph}
  40.     utReplace);  {a replacement of text within a paragraph}
  41.  
  42. type
  43.   PLineMap = ^LineMap;
  44.   LineMap  = array[1..High(SmallInt)] of Word;
  45.  
  46. type
  47.   {this variable sized structure is stored in a global undo}
  48.   {buffer and mapped into a TUndoNode as required}
  49.   PUndoRec = ^TUndoRec;
  50.   TUndoRec = record
  51.     PrevSize : Word;       {size of previous record}
  52.     Flags    : Byte;       {contains undo type and flags}
  53.     LinkNum  : Byte;       {link number}
  54.     PNum     : LongInt;    {paragraph number}
  55.     PPos     : Integer;    {position in paragraph}
  56.     DSize    : Word;       {data size}
  57.     Data     : record end; {data-dynamically allocated}
  58.   end;
  59.  
  60. const
  61.   UndoRecSize = SizeOf(TUndoRec);
  62.  
  63. type
  64.   TUndoNode = class(TObject)
  65.   public
  66.     UndoRec : PUndoRec;
  67.  
  68.     procedure Init(PUR   : PUndoRec;         {location in buffer}
  69.                    UT    : UndoType;
  70.                    Link  : Byte;
  71.                    MF    : Boolean;          {modified flag}
  72.                    PSize : Word;
  73.                    P     : LongInt;
  74.                    Pos   : Integer;
  75.                    D     : PAnsiChar;        {data}
  76.                    DLen  : Word);            {data length}
  77.       {-init the data fields of the object}
  78.     procedure InitReplace(PUR   : PUndoRec;  {location in buffer}
  79.                           Link  : Byte;
  80.                           MF    : Boolean;   {modified flag}
  81.                           PSize : Word;
  82.                           P     : LongInt;
  83.                           Pos   : Integer;
  84.                           D     : PAnsiChar; {data}
  85.                           DLen  : Word;      {data length}
  86.                           R     : PAnsiChar; {replace data}
  87.                           RLen  : Word);     {replace data length}
  88.       {-init the data fields of the object for a replace action}
  89.     procedure Done(PUR : PUndoRec);
  90.       {-conditionall destroy a paragraph node if associated}
  91.     function  GetUndoType(PUR : PUndoRec) : UndoType;
  92.       {-return the undo type for this undo record}
  93.     function  ModFlag(PUR : PUndoRec) : Boolean;
  94.       {-return the state of the modified flag}
  95.     procedure SetModFlag(PUR   : PUndoRec; Value : Boolean);
  96.       {-return the modified flag for this undo record}
  97.   end;
  98.  
  99.  
  100.   TParaNode = class(TObject)
  101.   public
  102.     BufSize   : Word;       {size of buffer}
  103.     LineCount : Integer;    {number of lines in this paragraph}
  104.     Map       : PLineMap;   {pointer to line map}
  105.     MapSize   : Word;       {number of elements in line map}
  106.     Next      : TParaNode;  {next paragraph in list}
  107.     Prev      : TParaNode;  {previous paragraph in list}
  108.     S         : PAnsiChar;  {text of paragraph; nil if empty}
  109.     SLen      : Word;       {current length}
  110.  
  111.     constructor Init(P       : PAnsiChar;
  112.                      WrapCol : Integer;
  113.                      TabSize : Integer);
  114.       {-create paragraph from text of P^}
  115.     constructor InitLen(P       : PAnsiChar;
  116.                         Len     : Word;
  117.                         WrapCol : Integer;
  118.                         TabSize : Integer);
  119.       {-create paragraph with Len characters from P^}
  120.     destructor Destroy;
  121.       override;
  122.  
  123.     function  GetS : PAnsiChar;
  124.       {-return pointer to text of paragraph}
  125.     function  ExpandToLength(NBS : Word) : Boolean;
  126.       {-expand buffer to size NBS}
  127.     function  EstimateMapSize(Len : Word; WrapCol : Integer) : Word;
  128.       {-return an estimated map size}
  129.     procedure ExpandLineMap(NMS : Word);
  130.       {-expand line map to size NMS}
  131.     procedure Recalc(WrapCol, TabSize : Integer);
  132.       {-calculate the number of lines in this paragraph given the specified
  133.         wrap column}
  134.     procedure RecalcAfterInsDel(WrapCol, TabSize, Pos, RplLen, Count : Integer;
  135.                                 var FL, LL : Integer);
  136.       {-calculate the number of lines after an insertion or deletion}
  137.     function  NthLine(N : Integer; var Len : Word) : PAnsiChar;
  138.       {-return a pointer to the Nth line of this paragraph; Len is its length}
  139.     function  PosToLine(Pos : Integer; var Col : Integer) : Integer;
  140.       {-given a position in the paragraph, return the line and Col}
  141.     function  InsertTextPrim(St : PAnsiChar; StLen : Word;
  142.                              Pos, WrapCol, TabSize : Integer;
  143.                              var FL, LL : Integer) : Word;
  144.       {-insert StLen characters from St^ at Pos}
  145.     function  InsertText(St : PAnsiChar; Pos, WrapCol, TabSize : Integer;
  146.                          var FL, LL : Integer) : Word;
  147.       {-insert St^ at Pos}
  148.     procedure DeleteText(Pos, Count, WrapCol, TabSize : Integer;
  149.                          var FL, LL : Integer);
  150.       {-delete count characters at Pos}
  151.     function  ReplaceText(Pos, Count, WrapCol, TabSize : Integer;
  152.                           St : PAnsiChar; StLen : Integer;
  153.                           var FL, LL : Integer) : Word;
  154.       {-replace the next Count characters at Pos with text of St^}
  155.     function  TrimWhiteSpace : Word;
  156.       {-trim trailing white space from end of paragraph}
  157.     function  CountWhiteSpace(Pos : Integer) : Word;
  158.       {-count amount of white space prior to Pos}
  159.   end;
  160. {.Z-}
  161.  
  162.  
  163. implementation
  164.  
  165. uses
  166.   SysUtils, OvcEditU, OvcMisc;
  167.  
  168.  
  169. const
  170.   {undo record bit flags}
  171.   urModFlag  = $80;
  172.   urTypeMask = $7F;
  173.  
  174.  
  175. {*** TUndoNode ***}
  176.  
  177. procedure TUndoNode.Done(PUR : PUndoRec);
  178. var
  179.   PPN : TParaNode;
  180. begin
  181.   {if this node is a deleted paragraph--then destroy it}
  182.   if GetUndoType(PUR) = utDelPara then begin
  183.     {put stored object pointer into temp para node}
  184.     move(PUR^.Data, PPN, PUR^.DSize);
  185.     PPN.Free;
  186.   end;
  187. end;
  188.  
  189. function TUndoNode.GetUndoType(PUR : PUndoRec) : UndoType;
  190. begin
  191.   Result := UndoType(PUR^.Flags and urTypeMask);
  192. end;
  193.  
  194. procedure TUndoNode.Init(PUR : PUndoRec; UT : UndoType; Link : Byte;
  195.                          MF : Boolean; PSize : Word; P : LongInt;
  196.                          Pos : Integer; D : PAnsiChar; DLen : Word);
  197. begin
  198.   with PUR^ do begin
  199.     PrevSize := PSize;
  200.     Flags := Ord(UT);
  201.     if MF then
  202.       Flags := Flags or urModFlag;
  203.     LinkNum  := Link;
  204.     PNum     := P;
  205.     PPos     := Pos;
  206.     DSize    := DLen;
  207.     if DLen <> 0 then
  208.       Move(D^, Data, DLen);
  209.   end;
  210. end;
  211.  
  212. procedure TUndoNode.InitReplace(PUR : PUndoRec; Link : Byte; MF : Boolean;
  213.                                 PSize : Word; P : LongInt; Pos : Integer;
  214.                                 D : PAnsiChar; DLen : Word; R : PAnsiChar; RLen : Word);
  215. var
  216.   DP : PAnsiChar;
  217. begin
  218.   with PUR^ do begin
  219.     PrevSize := PSize;
  220.     Flags := Ord(utReplace);
  221.     if MF then
  222.       Flags := Flags or urModFlag;
  223.     LinkNum  := Link;
  224.     PNum     := P;
  225.     PPos     := Pos;
  226.     DSize    := DLen+RLen+2;
  227.     DP       := @Data;
  228.     Move(D^, DP^, DLen);
  229.     DP[DLen] := #0;
  230.     Inc(DP, DLen+1);
  231.     Move(R^, DP^, RLen);
  232.     DP[RLen] := #0;
  233.   end;
  234. end;
  235.  
  236. function TUndoNode.ModFlag(PUR : PUndoRec) : Boolean;
  237. begin
  238.   Result := PUR^.Flags and urModFlag <> 0;
  239. end;
  240.  
  241. procedure TUndoNode.SetModFlag(PUR : PUndoRec; Value : Boolean);
  242. begin
  243.   with PUR^ do
  244.     if Value then
  245.       Flags := Flags or urModFlag
  246.     else
  247.       Flags := Flags and not urModFlag;
  248. end;
  249.  
  250.  
  251. {*** TParaNode ***}
  252.  
  253. function TParaNode.CountWhiteSpace(Pos : Integer) : Word;
  254.   {-Count amount of white space prior to Pos}
  255. var
  256.   L : Word;
  257. begin
  258.   Result := 0;
  259.   if S <> nil then begin
  260.     L := Pos;
  261.     while (L > 0) and edWhiteSpace(S[L-1]) do begin
  262.       Dec(L);
  263.       Inc(Result);
  264.     end;
  265.   end;
  266. end;
  267.  
  268. procedure TParaNode.DeleteText(Pos, Count, WrapCol, TabSize : Integer;
  269.                                var FL, LL : Integer);
  270.   {-Delete count characters at Pos}
  271. begin
  272.   if S = nil then
  273.     Exit;
  274.   if Pos > SLen then
  275.     Exit;
  276.   Dec(Pos);
  277.   if Pos+Count >= SLen then begin
  278.     SLen := Pos;
  279.     S[Pos] := #0;
  280.   end else begin
  281.     edDeleteSubString(S, SLen, Count, Pos);
  282.     Dec(SLen, Count);
  283.   end;
  284.   RecalcAfterInsDel(WrapCol, TabSize, Pos, 0, -Count, FL, LL);
  285. end;
  286.  
  287. destructor TParaNode.Destroy;
  288.   {-Destroy the paragraph}
  289. begin
  290.   if (S <> nil) then begin
  291.     FreeMem(S, BufSize);
  292.     S := nil;
  293.   end;
  294.  
  295.   if (Map <> nil) then begin
  296.     FreeMem(Map, MapSize*SizeOf(Word));
  297.     Map := nil;
  298.   end;
  299.  
  300.   inherited Destroy;
  301. end;
  302.  
  303. function TParaNode.EstimateMapSize(Len : Word; WrapCol : Integer) : Word;
  304.   {-Return an estimated map size}
  305. var
  306.   MS : Word;
  307. begin
  308.   if (WrapCol = High(SmallInt)) or (WrapCol = 0) then
  309.     Result := 1
  310.   else begin
  311.     MS := (Len div WrapCol);
  312.     Inc(MS, MS div 5);
  313.     MS := (MS+7) and $FFF8;
  314.     if MS < 8 then
  315.       MS := 8;
  316.     Result := MS;
  317.   end;
  318. end;
  319.  
  320. procedure TParaNode.ExpandLineMap(NMS : Word);
  321.   {-Expand line map to size NMS}
  322. var
  323.   NMap : PLineMap;
  324. begin
  325.   NMS := (NMS+$7) and $FFF8;
  326.   if NMS < 8 then
  327.     NMS := 8;
  328.   if NMS <= MapSize then
  329.     Exit;
  330.  
  331.   GetMem(NMap, NMS*SizeOf(Word));
  332.   FillChar(NMap^, NMS*SizeOf(Word), 0);
  333.  
  334.   edMoveFast(Map^, NMap^, MapSize*SizeOf(Word));
  335.  
  336.   FreeMem(Map, MapSize*SizeOf(Word));
  337.  
  338.   Map := NMap;
  339.   MapSize := NMS;
  340. end;
  341.  
  342. function TParaNode.ExpandToLength(NBS : Word) : Boolean;
  343.   {-Expand buffer to size NBS}
  344. var
  345.   P : PAnsiChar;
  346. begin
  347.   Result := False;
  348.   if NBS > BufSize then begin
  349.     NBS := (NBS+$F) and $FFF0;
  350.     GetMem(P, NBS);
  351.     if P = nil then
  352.       Exit;
  353.     if (BufSize <> 0) then begin
  354.       if SLen+1 >= 1024 then
  355.         edMoveBlock(S^, P^, SLen+1)
  356.       else
  357.         edMoveFast(S^, P^, SLen+1);
  358.  
  359.       FreeMem(S, BufSize);
  360.     end else
  361.       P^ := #0;
  362.     S := P;
  363.     BufSize := NBS;
  364.   end;
  365.   Result := True;
  366. end;
  367.  
  368. function TParaNode.GetS : PAnsiChar;
  369.   {-Return pointer to text of paragraph}
  370. begin
  371.   if S = nil then
  372.     Result := ''
  373.   else
  374.     Result := S;
  375. end;
  376.  
  377. constructor TParaNode.Init(P : PAnsiChar; WrapCol, TabSize : Integer);
  378.   {-Create paragraph from text of P^}
  379. begin
  380.   InitLen(P, StrLen(P), WrapCol, TabSize);
  381.   {InitLen calls inherited Create}
  382. end;
  383.  
  384. constructor TParaNode.InitLen(P : PAnsiChar; Len : Word;
  385.                               WrapCol, TabSize : Integer);
  386.   {-Create paragraph with Len characters from P^}
  387. var
  388.   Size : Word;
  389. begin
  390.   inherited Create;
  391.  
  392.   Map := nil;
  393.   Next := nil;
  394.   Prev := nil;
  395.   Size := Len+1;
  396.   LineCount := 1;
  397.  
  398.   {make copy of line}
  399.   if Size = 1 then begin
  400.     S := nil;
  401.     BufSize := 0;
  402.   end else begin
  403.     BufSize := (Size+7) and $FFF8;
  404.     GetMem(S, BufSize);
  405.     if S = nil then
  406.       raise EOutOfMemory.Create(GetOrphStr(SCOutOfMemory));
  407.     StrLCopy(S, P, Len);
  408.   end;
  409.   SLen := Len;
  410.  
  411.   {allocate initial line map}
  412.   MapSize := EstimateMapSize(Len, WrapCol);
  413.   GetMem(Map, MapSize*SizeOf(Word));
  414.   if Map = nil then
  415.     raise EOutOfMemory.Create(GetOrphStr(SCOutOfMemory));
  416.  
  417.   FillChar(Map^, MapSize*SizeOf(Word), 0);
  418.   Recalc(WrapCol, TabSize);
  419. end;
  420.  
  421. function TParaNode.InsertTextPrim(St : PAnsiChar; StLen : Word;
  422.                                   Pos, WrapCol, TabSize : Integer;
  423.                                   var FL, LL : Integer) : Word;
  424.   {-Insert StLen characters from St^ at Pos}
  425. var
  426.   NBS : Word;
  427. begin
  428.   Dec(Pos);
  429.   if Pos > SLen then
  430.     NBS := Pos
  431.   else
  432.     NBS := SLen;
  433.   Inc(NBS, StLen+1);
  434.   if not ExpandToLength(NBS) then begin
  435.     Result := oeOutOfMemory;
  436.     Exit;
  437.   end;
  438.  
  439.   if Pos > SLen then begin
  440.     edPadPrim(S, Pos);
  441.     SLen := Pos;
  442.   end;
  443.  
  444.   edStrStInsert(S, St, SLen, StLen, Pos);
  445.   Inc(SLen, StLen);
  446.   RecalcAfterInsDel(WrapCol, TabSize, Pos, 0, StLen, FL, LL);
  447.   Result := 0;
  448. end;
  449.  
  450. function TParaNode.InsertText(St : PAnsiChar; Pos, WrapCol, TabSize : Integer;
  451.                               var FL, LL : Integer) : Word;
  452.   {-Insert St^ at Pos}
  453. begin
  454.   Result := InsertTextPrim(St, StrLen(St), Pos, WrapCol, TabSize, FL, LL);
  455. end;
  456.  
  457. function TParaNode.NthLine(N : Integer; var Len : Word) : PAnsiChar;
  458.   {-Return a pointer to the Nth line of this paragraph; Len is its length}
  459. var
  460.   S1 : PAnsiChar;
  461. begin
  462.   if (N < 1) or (N > LineCount) then begin
  463.     S1 := '';
  464.     Len := 0;
  465.   end else if LineCount = 1 then begin
  466.     S1 := GetS;
  467.     Len := SLen;
  468.   end else begin
  469.     S1 := S;
  470.     Inc(S1, Map^[N]);
  471.     if N = LineCount then
  472.       Len := StrLen(S1)
  473.     else
  474.       Len := Map^[N+1]-Map^[N];
  475.   end;
  476.   Result := S1;
  477. end;
  478.  
  479. function TParaNode.PosToLine(Pos : Integer; var Col : Integer) : Integer;
  480.   {-Given a position in the paragraph, return the line and Col}
  481. var
  482.   I : Word;
  483.   LC : Integer;
  484. begin
  485.   if LineCount = 1 then begin
  486.     Col := Pos;
  487.     Result := 1;
  488.   end else begin
  489.     {make sure we don't have to search more than 1/4 of the line map}
  490.     LC := LineCount;
  491.     if (LC > 20) then
  492.       if (Pos <= Map^[LC div 2]) then begin
  493.         LC := LC div 2;
  494.         if (Pos <= Map^[LC div 2]) then
  495.           LC := LC div 2;
  496.       end else if (Pos <= Map^[LC-(LC div 2)]) then
  497.         Dec(LC, LC div 2);
  498.     I := edFindPosInMap(Map, LC, Pos);
  499.     Col := Pos-Map^[I];
  500.     Result := I;
  501.   end;
  502. end;
  503.  
  504. procedure TParaNode.Recalc(WrapCol, TabSize : Integer);
  505.   {-Calculate the number of lines in this paragraph given the specified
  506.     wrap column}
  507. var
  508.   P, LP : PAnsiChar;
  509.   Len, MS : Word;
  510.   WC : Integer;
  511.   HT : Boolean;
  512. begin
  513.   LineCount := 1;
  514.   if (WrapCol = High(SmallInt)) or (WrapCol = 0) or (S = nil) then
  515.     Exit;
  516.  
  517.   P := S;
  518.   Len := SLen;
  519.  
  520.   {do we need to expand the line map before we start?}
  521.   MS := EstimateMapSize(Len, WrapCol);
  522.   if MS > MapSize then
  523.     ExpandLineMap(MS);
  524.  
  525.   HT := (Len > 0) and edHaveTabs(P, Len);
  526.   if HT then
  527.     WC := edGetActualCol(P, WrapCol, TabSize)
  528.   else
  529.     WC := WrapCol;
  530.  
  531.   LP := P;
  532.   while Len > WC do begin
  533.     P := edFindNextLine(LP, WC);
  534.     Dec(Len, PtrDiff(P, LP));
  535.     if Len > 0 then begin
  536.       Inc(LineCount);
  537.  
  538.       {do we need to expand the line map?}
  539.       if LineCount > MapSize then
  540.         ExpandLineMap(LineCount);
  541.       Map^[LineCount] := PtrDiff(P, S);
  542.  
  543.       if HT then
  544.         WC := edGetActualCol(P, WrapCol, TabSize)
  545.       else if WrapCol > Len then
  546.         WC := Len
  547.       else
  548.         WC := WrapCol;
  549.       LP := P;
  550.     end;
  551.   end;
  552. end;
  553.  
  554. procedure TParaNode.RecalcAfterInsDel(WrapCol, TabSize, Pos : Integer;
  555.                                       RplLen, Count : Integer;
  556.                                       var FL, LL : Integer);
  557.   {-Calculate the number of lines after an insertion, deletion, or
  558.     replacement}
  559. label
  560.   ExitPoint;
  561. var
  562.   P, LP : PAnsiChar;
  563.   Len, O, PO, ML, PML : Word;
  564.   WC, OL, I, L, C  : Integer;
  565.   HT : Boolean;
  566. begin
  567.   L := PosToLine(Pos+1, C);
  568.   OL := L;
  569.  
  570.   if (WrapCol = High(SmallInt)) or (WrapCol=0) or (S = nil) then begin
  571.     FL := L;
  572.     LL := L;
  573.     Exit;
  574.   end;
  575.  
  576.   if L > 1 then
  577.     Dec(L);
  578.  
  579.   LP := NthLine(L, Len);
  580.   Len := SLen-Map^[L];
  581.  
  582.   HT := (Len > 0) and edHaveTabs(LP, Len);
  583.   if HT then
  584.     WC := edGetActualCol(LP, WrapCol, TabSize)
  585.   else
  586.     WC := WrapCol;
  587.  
  588.   FL := 0;
  589.   LL := 0;
  590.   ML := Map^[L];
  591.   PO := ML;
  592.   while Len > WC do begin
  593.     {get the start of the next line}
  594.     P := edFindNextLine(LP, WC);
  595.  
  596.     {adjust the remaining length}
  597.     Dec(Len, PtrDiff(P, LP));
  598.  
  599.     if Len > 0 then begin
  600.       Inc(L);
  601.  
  602.       {do we need to expand the line map?}
  603.       if L > MapSize then
  604.         ExpandLineMap(L);
  605.  
  606.       O := PtrDiff(P, S);
  607.       PML := ML;
  608.       ML := Map^[L];
  609.  
  610.       {did the length of the previous line change?}
  611.       if (FL = 0) and (ML <> 0) and (Pos >= ML) and (Pos < O) then begin
  612.         LL := L;
  613.         FL := L-1;
  614.         Map^[L] := O;
  615.       end else if (ML <> 0) and (ML = O-Count) and
  616.                   ((RplLen = 0) or (O >= Pos+RplLen)) then begin
  617.         {the line breaks didn't change from this point on}
  618.         for I := L to LineCount do
  619.           {all we need to do is adjust the offsets}
  620.           Inc(Map^[I], Count);
  621.         goto ExitPoint;
  622.       end else begin
  623.         if FL = 0 then
  624.           FL := L;
  625.         LL := L;
  626.  
  627.         if (RplLen = 0) and (Abs(Count) <= WC) and (ML <> 0) then
  628.           {was a whole line deleted?}
  629.           if (ML = PO-Count) and (Count < 0) and (Pos < O) then begin
  630.             edMoveFast(Map^[L+1], Map^[L], (LineCount-L)*SizeOf(Word));
  631.             Dec(LineCount);
  632.             for I := L to LineCount do
  633.               Inc(Map^[I], Count);
  634.             goto ExitPoint;
  635.           end else if (O = PML+Count) and (Count > 0) and (Pos < O) then begin
  636.             {a whole line inserted?}
  637.             Inc(LineCount);
  638.             ExpandLineMap(LineCount);
  639.             edMoveFast(Map^[L], Map^[L+1], (LineCount-L)*SizeOf(Word));
  640.             Map^[L] := O;
  641.             for I := L+1 to LineCount do
  642.               Inc(Map^[I], Count);
  643.             goto ExitPoint;
  644.           end;
  645.         Map^[L] := O;
  646.       end;
  647.       PO := O;
  648.  
  649.       if HT then
  650.         WC := edGetActualCol(P, WrapCol, TabSize)
  651.       else if WrapCol > Len then
  652.         WC := Len
  653.       else
  654.         WC := WrapCol;
  655.       LP := P;
  656.     end;
  657.   end;
  658.  
  659.   LineCount := L;
  660.  
  661. ExitPoint:
  662.   if MapSize > LineCount then
  663.     Map^[LineCount+1] := 0;
  664.   if (FL = 0) then
  665.     if OL = 1 then
  666.       FL := OL
  667.     else
  668.       FL := OL-1
  669.   else if (FL > OL) then
  670.     FL := OL;
  671.   if LL = 0 then
  672.     LL := OL;
  673. end;
  674.  
  675. function TParaNode.ReplaceText(Pos, Count, WrapCol, TabSize : Integer;
  676.                                St : PAnsiChar; StLen : Integer;
  677.                                var FL, LL : Integer) : Word;
  678.   {-Replace the next Count characters at Pos with text of St^}
  679. var
  680.   L, Delta, FL1, LL1 : Integer;
  681. begin
  682.   Dec(Pos);
  683.   Delta := StLen-Count;
  684.   if Delta > 0 then
  685.     if not ExpandToLength(SLen+Delta+1) then begin
  686.       Result := oeOutOfMemory;
  687.       Exit;
  688.     end;
  689.  
  690.   if (StLen > 0) and (Count > 0) then begin
  691.     if Delta >= 0 then
  692.       L := Count
  693.     else
  694.       L := StLen;
  695.     Move(St^, S[Pos], L);
  696.     RecalcAfterInsDel(WrapCol, TabSize, Pos, L, L, FL1, LL1);
  697.   end else begin
  698.     FL1 := High(SmallInt);
  699.     LL1 := 0
  700.   end;
  701.  
  702.   if Delta < 0 then
  703.     edDeleteSubString(S, SLen, -Delta, Pos+StLen)
  704.   else if Delta > 0 then
  705.     edStrStInsert(S, @St[Count], SLen, Delta, Pos+Count);
  706.  
  707.   if Delta <> 0 then begin
  708.     Inc(SLen, Delta);
  709.     RecalcAfterInsDel(WrapCol, TabSize, Pos, 0, Delta, FL, LL);
  710.   end;
  711.  
  712.   if (Delta = 0) or (FL1 < FL) then
  713.     FL := FL1;
  714.   if (Delta = 0) or (LL1 > LL) then
  715.     LL := LL1;
  716.  
  717.   Result := 0;
  718. end;
  719.  
  720. function TParaNode.TrimWhiteSpace : Word;
  721.   {-Trim trailing white space from end of paragraph}
  722. var
  723.   L, N : Word;
  724. begin
  725.   N := 0;
  726.   if S <> nil then begin
  727.     L := SLen;
  728.     while (L > 0) and edWhiteSpace(S[L-1]) do
  729.       Dec(L);
  730.     N := SLen-L;
  731.     S[L] := #0;
  732.     SLen := L;
  733.   end;
  734.   Result := N;
  735. end;
  736.  
  737.  
  738. end.
  739.